package com.mofeng.myshop.service.fileupload.impl;

import com.mofeng.myshop.exception.MyException;
import com.mofeng.myshop.service.fileupload.FileServer;
import com.mofeng.myshop.until.Constants;
import com.mofeng.myshop.until.MyUtil;
import com.mofeng.myshop.until.ServletUtils;
import com.mofeng.myshop.until.component.FtpUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * 文件上传，本地实现
 */
@Service(Constants.Settings.FILE_UPLOAD_TYPE + "ftp")
@Slf4j
@RequiredArgsConstructor
public class FileFtpServerImpl implements FileServer {

    private final FtpUtil ftpUtil;

    /**
     * 添加文件
     *
     * @param file       文件
     * @param pathPrefix 文件的基础存储路径
     * @param id         文件的id
     * @return {文件URL，文件的实际物理地址}
     */
    @Override
    public String[] saveFile(MultipartFile file, String pathPrefix, String id) {
        try {
            //创建图片的保存目录（保存规则:配置目录 日期 类型 ID.类型)
            long currentTimeMillis = System.currentTimeMillis();
            String fileType = MyUtil.FileUtil.getFileType(file,defaultImageType);
            String currentDay = MyUtil.DateUtil.getTimeStr(currentTimeMillis, "yyyy_MM_dd");
            String dayPath = pathPrefix + currentDay;
            String newPath = dayPath + File.separator + fileType;
            String fileName = id + "." + fileType;
            MyUtil.FileUtil.checkAndCreateDirectory(newPath);
            String url = currentTimeMillis + "_" + id + "." + fileType;
            boolean upload = ftpUtil.upload(newPath, fileName, file.getInputStream());
            String path = newPath + File.separator + fileName;
            if (!upload) {
                log.error("put       {}", path);
                throw new RuntimeException("图片上传失败，请重试检查");
            }
            return new String[]{url, path};
        } catch (Exception e) {
            throw new RuntimeException("文件存储发生错误", e);
        }
    }

    /**
     * 删除文件
     *
     * @param basePath 文件基础路径
     * @param url      文件路径
     */
    @Override
    public String delFile(String basePath, String url) {
        try {
            String[] file = parseFilePath(basePath, url);
            ftpUtil.deleteFile(file[0], file[1]);
            return file[2];
        } catch (Exception e) {
            throw new RuntimeException("图片删除失败，请检查重试~");
        }
    }

    /**
     * 解析路径
     *
     * @param url 文件路径
     * @return 返回文件路径的关键字
     */
    @Override
    public String parseFileId(String url) {
        return parseFilePath("", url)[1];
    }

    /**
     * 获取文件
     *
     * @param url 文件路径
     */
    @Override
    public void getFile(String basePath, String url) {
        try {
            String[] fileMsg = parseFilePath(basePath, url);
            String name = fileMsg[1];
            String imagesPath = fileMsg[0];
            HttpServletResponse response = ServletUtils.getResponse();
            InputStream fos = null;
            try (OutputStream writer = response.getOutputStream();) {
                response.setContentType("image/png");
                FTPClient ftpClient = ftpUtil.getFtpClient();
                fos = ftpUtil.download(ftpClient, imagesPath, name);
                if (fos == null) {
                    return;
                }
                // 读取文件内容到字节数组
                writer.write(fos.readAllBytes());
                writer.flush();
            } catch (NullPointerException e) {
                MyUtil.ErrorUtil.printError(e);
            } finally {
                if (fos != null) {
                    fos.close();
                }
            }
        } catch (Exception e) {
            throw new MyException("图片获取失败", e);
        }
    }

    /**
     * 解析文件路径
     *
     * @param basePath 基础路径
     * @param url      URL
     * @return [文件物理地址,名称,id]
     */
    private String[] parseFilePath(String basePath, String url) {
        String[] path = url.split("_");
        String dayValue = MyUtil.DateUtil.getTimeStr(Long.parseLong(path[0]), "yyyy_MM_dd");
        String name = path[1];
        String type = name.split("\\.")[1];
        String id = name.replace(type, "").replace(".", "");
        String filePath = new StringBuffer(basePath)
                .append(dayValue).append(File.separator)
                .append(type).toString();
        return new String[]{filePath, name, id};
    }
}
